package remote.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;

import android.util.Base64;
import android.util.Log;

import remote.constants.IRequestTypes;

public class Client
{
	private final static int SERVER_PORT = 12345;
	private final static int CLIENT_PORT = 12346;
	private final static String BROADCAST_ADDRESS = "192.168.1.255";
	private final static String REQUEST_FORMAT = "%1$s;%2$s";
	private static DatagramSocket _datagram;
	private static Socket _socket;
	
	public Client(String ipAddress) throws Exception
	{
		_datagram = new DatagramSocket(CLIENT_PORT, InetAddress.getByName(ipAddress));
	}
	
	public Client()
	{
		try
		{
			byte[] buffer = new byte[512];
			byte[] data = String.format(REQUEST_FORMAT, IRequestTypes.CONNECTION, "").getBytes();
			_datagram = new DatagramSocket(CLIENT_PORT);
			DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(BROADCAST_ADDRESS), SERVER_PORT);
			_datagram.setBroadcast(true);
			
			// Send data
			_datagram.send(packet);
			packet = new DatagramPacket(buffer, buffer.length);
			_datagram.setSoTimeout(20000);
			
			// Receive data
			_datagram.receive(packet);
			Log.i("data", new String(packet.getData()).trim());
			// Connection to the server
			if(packet.getData().length > 0)
				_datagram.connect(packet.getSocketAddress());
			
			//_datagram.setBroadcast(false);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			
			if(_datagram.isConnected())
				_datagram.disconnect();
		}
	}
	
	public String send(int requestType, int action)
	{
		return send(requestType, Integer.valueOf(action).toString());
	}
	
	public String send(int requestType, String requestData)
	{
		StringBuilder serverResponse = new StringBuilder();
		
		try
		{
			boolean isLastPacket = false;
			byte[] data = String.format(REQUEST_FORMAT, requestType, requestData).getBytes();
			
			if(_socket == null)
			{
				byte[] buffer = new byte[512];
				DatagramPacket packet = new DatagramPacket(data, data.length, _datagram.getInetAddress(), _datagram.getPort());
				Log.i("request", new String(packet.getData()));
				_datagram.send(packet);
				packet = new DatagramPacket(buffer, buffer.length);
				
				// Get server response
				while(!isLastPacket)
				{
					_datagram.receive(packet);
					
					String[] response = new String(packet.getData()).trim().split(";", 3);
					
					Log.i("response", new String(packet.getData(), "ISO-8859-1").trim() + "");
					
					if(response.length == 3)
					{
						isLastPacket = Integer.parseInt(response[1])  == 1 ? true : false;
						serverResponse.append(response[2]);
					}
				}
				
				Log.i("data", serverResponse.toString());
			}
			else
			{
				PrintStream output = new PrintStream(_socket.getOutputStream());
				output.println(data);
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		
		return serverResponse.toString();
	}
	
	public String getResponseData(String response)
	{
		String[] responseValues = response.split(";", 3);
		String data = "";
		Log.i("data", responseValues.length + ", data : " + data);
		if(responseValues.length == 3)
			data = responseValues[1];
		
		return data;
	}
	
	public int getResponseReturnCode(String response)
	{
		String[] responseValues = response.split(";", 3);
		int returnCode = 0;
		
		if(responseValues.length == 3)
			returnCode = Integer.parseInt(responseValues[0]);
		
		return returnCode;
	}
	
	public void close()
	{
		try
		{
			if(_socket != null)
				_socket.close();
			
			if(_datagram != null)
				_datagram.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public boolean isConnected()
	{
		return _datagram.isConnected();
	}
}
